home *** CD-ROM | disk | FTP | other *** search
- % CWEB source for FrontPubScreen
- % 12 Apr 1992 john fieber (jfieber@@sophia.smith.edu)
-
- \nocon % omit table of contents
- \datethis % print date on listing
- \def\progname{\.{FrontPubScreen}}
-
- @* FrontPubScreen. This program is for AmigaDOS 2.0 or later. It does
- one simple and useful thing when you are working with public screens:
- if the frontmost screen is a public screen, it returns the name of
- that screen. Since the the front screen is generally the one you are
- working on, it effectively returns the name of the screen you are
- working on.
-
- A good example of how this can be used is with a ``hotkey'' program
- for opening pop-up utilities, command shells, editors or whatever. To
- illustrate, in this CLI command: $$\hbox{\tt NewCLI
- CON:20/50/540/180/AmigaShell/AUTO/SCREEN`\progname`}$$
- \.{`\progname`} will be replaced by the output of \progname. Since
- \progname\ displays the name of the front screen, the result the
- above command is a CLI window opening up on whatever screen you
- happen to be working on. This command attached to a hot-key provides
- an instant CLI on whatever screen you happen to be working on. Other
- programs that allow you to specify a screen to open on can use the
- same technique. For TurboText users, try: $$\hbox{\tt ttx screen
- `progname`}$$ attached to a hotkey.
-
- Unfortunately this nifty feature only works if the front screen is
- indeed a public screen. Fortunately there are a growing number of
- programs that do open public screens. Also, you can create your own
- using one of the various public screen managers roaming around the
- ``net''.
-
- @ {\bf Copying.} Feel free to copy and distribute this program but
- please don't distribute the executable without this source code.
- Also, feel free to make changes but please make and document the
- changes in a cweb change file, not the original. Also, I encourage
- people who are writing little pop-up type applications to stick this
- little bit of code in. Public screens are nifty things so use them
- and make them useful!
-
- If you do make a change file, use the code in your own program, or
- otherwise find this program useful I would like to hear about it.
- Send email to John Fieber at \.{jfieber@@sophia.smith.edu}.
-
- @ Okay, enough description, now on to the program, starting with a
- little thing to teach \.{cweave} about one of the special Amiga
- types\dots
-
- @f ULONG int
-
- @ All good AmigaDOS programs should have string such as the following
- embedded somewhere in the program. The CLI command \.{Version} will
- look for this string and display it if found. This approach is much
- easier than writing in code to provide a command line switch and to
- display the version and much more consistant from the user's point of
- view.
-
- @c
- char version[] = "\0$VER: FrontPubScreen 1.0 (4.12.92)";
-
- @ Here is the general layout of the program. We first check the
- value of |argc| to determine if the program was run from a command
- shell or from the Workbench. If |argc == 0| then \progname\ was
- started from the Workbench. Since it has no useful function in that
- context, we just exit. If |argc >= 1| then we move on and try the
- name of a useful public screen.
-
- @c
- @<Include files@>@;
-
- @<Function prototypes@>@;
-
- @<Global variables@>@;
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- if (argc) {
- @<Open system libraries@>;
- @<Get screen name@>;
- @<Output screen name@>;
- @<Close system libraries@>@;
- }
- }
-
- @ We don't really need to include the extra baggage of \.{stdio.h}
- either during compilation or linking since AmigaDOS provides for
- writing things out to the console. But we {\it do\/} need to include
- the headers to get at those system functions.
-
- @<Include files@>=
- #include <exec/types.h>
- #include <intuition/intuition.h>
- #include <intuition/intuitionbase.h>
- #include <dos/dos.h>
-
- @ We also want to include the the Commodore function prototypes to be
- ANSI compliant and the \#{\bf pragma}'s to bypass the library access
- functions in \.{amiga.lib} that make the code unnecessairly large and
- slow.
-
- @<Function prototypes@>=
-
- #include <proto/intuition.h>
- #include <proto/dos.h>
- #include <proto/exec.h>
-
-
- @ The variable |IntuitionBase| is a pointer to base address of the
- Intuition Library. The value returned by the |OpenLibrary()| call
- will be placed here. Also needed is a place to store the name of the
- public screen that the program will return. The value for
- |MAXPUBSCREENNAME| is defined in \.{screens.h} (which is included
- with \.{intuition.h}). Finally, we have a pointer to a screen
- structure.
-
- @<Global variables@>=
-
- struct IntuitionBase *IntuitionBase;
- char public_screen_name[MAXPUBSCREENNAME];
- struct Screen *public_screen_address;
-
- @ Now we must open the Intuition library so we can get at the nifty
- system functions for twiddling with screens. If the call to
- |OpenLibrary()| fails, it will return |NULL|. We must exit
- gracefully in the event that this occurs.
-
- Notice that since Intuition has its own non-standard library
- structure we must typecast the |OpenLibrary()| function which by
- definition returns a pointer to a standard library structure.
-
- @<Open system libraries@>=
-
- IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",36L);
- if (!IntuitionBase) {
- exit(20L);
- }
-
- @ To clean up at the end of the program, the Intuition library must
- be closed. Again since Intuition has a non-standard library structure
- we need to typecast it so that the use of |CloseLibrary()| matches
- its definition.
-
- @<Close system libraries@>=
-
- CloseLibrary((struct Library *) IntuitionBase);
-
- @ Moving right along, here is the code that prints out the
- (hopefully) useful information regarding a public screen name. The
- variable |public_screen_name| is assumed to contain the screen name
- of the front public screen, or the default public screen. Just to
- check its validity, we try to lock the screen. In the event that
- fails we just return \.{Workbench} which should always work in some
- way shape or form.
-
- @<Output screen name@>=
-
- public_screen_address = LockPubScreen(public_screen_name);
- if (public_screen_address) {
- (void) PutStr(public_screen_name);
- (void) PutStr("\n");
- UnlockPubScreen(NULL, public_screen_address);
- }
- else {
- (void) PutStr("Workbench\n");
- }
-
- @ Now we must figure out some useful information for the previous
- section to display. A couple more variables must be defined to aid in the
- search for the name of the front public screen.
-
- @<Global variables@>=
-
- ULONG intuition_lock;
- struct Screen *front_screen_address;
- struct List *public_screen_list;
- struct PubScreenNode *public_screen_node;
-
- @ The address of the front screen is easily found in the
- |IntuitionBase| structure. However, since this is a system structure
- that we are not normally at liberty to examine, we must first get
- permission from Intuition to examine it. This is accomplished with
- the |LockIBase()| function which sets up a semaphore. This is much
- friendlier than simply locking the whole system with |forbid()|
- and |permit()| while we look at the structure.
-
- With the address of the frontmost screen in hand, we check to see if
- it is a public or Workbench screen. If so, we search the public
- screen list for a match. The variable |public_screen_name| is set to
- a |NULL| string at the start and then checked at the end. If it is
- still |NULL|, then the front screen was not found in the public
- screen list so we ask the system for the name of the default public
- screen.
-
- @<Get screen name@>=
-
- public_screen_name[0] = '\0';
-
- intuition_lock = LockIBase(0L);
- front_screen_address = IntuitionBase->FirstScreen;
- if ((front_screen_address->Flags & PUBLICSCREEN) || (front_screen_address->Flags & WBENCHSCREEN)) {
- UnlockIBase(intuition_lock);
- @<Search public screen list@>;
- }
- else {
- UnlockIBase(intuition_lock);
- }
-
- if (public_screen_name[0] == '\0') {
- GetDefaultPubScreen(public_screen_name);
- }
-
-
- @ Here we lock the public screen list and examine it
- looking for a match to |front_screen_address|. If one is found,
- we then copy the name of the screen into |public_screen_name| for
- later use. Note that the AutoDocs mention that the screen pointer in
- the |PubScreenNode| structure is not trustworthy. However, in this
- case nothing catastrophic will happen though if it is wrong---the
- program won't work right but it should not affect anything else.
-
- @<Search public screen list@>=
-
- public_screen_list = LockPubScreenList();
- public_screen_node = (struct PubScreenNode *) public_screen_list->lh_Head;
- while (public_screen_node) {
- if (public_screen_node->psn_Screen == front_screen_address) {
- strcpy(public_screen_name, public_screen_node->psn_Node.ln_Name);
- break;
- }
- public_screen_node = (struct PubScreenNode *) public_screen_node->psn_Node.ln_Succ;
- }
- UnlockPubScreenList();
-
- @ And thus we are finished!
-
- @ {\bf Other notes.} There are still a few problems that hopefully
- won't be too problematic. Basically, although a public screen may be
- available when \progname\ runs, there is no guarantee that it will
- still be around later when that screen is used by whatever
- called \progname. In order to ensure this we would have to maintain
- a lock on the screen until the caller has locked the screen, either
- with |LockPubScreen()| or by having a window open on it.
-
- To do this properly would require communication between the
- applications so you might as well just build the \progname\ right
- in and not bother with this silly utility. Alternately
- \progname\ could start another process to hold the lock for a
- while and possibly monitor the visitor count on the screen. This
- might help but the payoff would probably be much smaller than the
- effort involved to implement it.
-
- Also, if the comments and explainations of this program seem a bit
- excessive it is because I'm just learning how to use this nifty
- invention of D.~Knuth called \.{CWEB}.
- \medskip\rightline{--john fieber}
-
- @* Index.
-